/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2004
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
*
* Author's email : insane@dees.ufmg.br
* Author's Website : http://www.dees.ufmg.br/insane
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package br.ufmg.dees.insane.model.xfemModel.enrichmentItem;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

import br.ufmg.dees.insane.model.xfemModel.XFemModel;
import br.ufmg.dees.insane.model.xfemModel.crackGrowthDirectionLaw.CrackGrowthDirectionLaw;
import br.ufmg.dees.insane.model.xfemModel.crackGrowthDirectionLaw.NonLocalPrincipalStressDirection;
import br.ufmg.dees.insane.model.xfemModel.crackGrowthIncrementLaw.BoundaryElementIncrement;
import br.ufmg.dees.insane.model.xfemModel.crackGrowthIncrementLaw.CrackGrowthIncrementLaw;
import br.ufmg.dees.insane.model.xfemModel.enrichmentDetector.EnrichmentDetector;
import br.ufmg.dees.insane.model.xfemModel.enrichmentFunction.EnrichmentFunction;
import br.ufmg.dees.insane.model.xfemModel.geometryEntity.GeometryEntity;
import br.ufmg.dees.insane.model.xfemModel.xfemElement.XFEMElement;

/**
 * @author Kelson Wolff
 *
 */
public abstract class EnrichmentItem implements java.io.Serializable{
	
	/**
	 * Comment for <code>serialVersionUID</code>
	 */
	private static final long serialVersionUID = 1L;
	
	protected GeometryEntity myGeometry;
	protected List<EnrichmentFunction> myEnrichFns;
	protected EnrichmentDetector myEnrDetector;
	protected List<XFEMElement> interactedElements;
	protected int[] numDofOnWhichEnrichFnsAct;
	protected int totalNumberOfAdditionalDofs;
	protected String label;
	

	/**
	 * CONSTRUCTOR
	 */
	public EnrichmentItem() {
		super();
		// TODO Auto-generated constructor stub
		this.myGeometry = null;
		this.myEnrichFns = new ArrayList<EnrichmentFunction>();
		this.myEnrDetector = null;
		this.interactedElements = new ArrayList<XFEMElement>();
		this.numDofOnWhichEnrichFnsAct = null;
		this.totalNumberOfAdditionalDofs = -1;
	}
	
	
	/**
	 * @return Returns the label.
	 */
	public String getLabel() {
		return label;
	}


	/**
	 * @param label The label to set.
	 */
	public void setLabel(String label) {
		this.label = label;
	}


	/**
	 * @return Returns the interactedElements.
	 */
	public List<XFEMElement> getInteractedElements() {
		return interactedElements;
	}

	
	/**
	 * @param interactedElements The interactedElements to set.
	 */
	public void setInteractedElements(List<XFEMElement> interactedElements) {
		this.interactedElements = interactedElements;
	}
	
	/**
	 * 
	 * @param e The XFEMElement to set.
	 */
	public void setInteractedElements(XFEMElement e){
		if(!this.getInteractedElements().contains(e)){
			this.interactedElements.add(e);
		}
	}


	/**
	 * @return Returns the myEnrDetector.
	 */
	public EnrichmentDetector getMyEnrDetector() {
		return myEnrDetector;
	}


	/**
	 * @param myEnrDetector The myEnrDetector to set.
	 */
	public void setMyEnrDetector(EnrichmentDetector myEnrDetector) {
		this.myEnrDetector = myEnrDetector;
	}


	/**
	 * @return Returns the myGeometry.
	 */
	public GeometryEntity getMyGeometry() {
		return myGeometry;
	}


	/**
	 * @param myGeometry The myGeometry to set.
	 */
	public void setMyGeometry(GeometryEntity myGeometry) {
		this.myGeometry = myGeometry;
	}


	/**
	 * @return Returns the myEnrichFns.
	 */
	public List<EnrichmentFunction> getMyEnrichFns() {
		return myEnrichFns;
	}

	
	/**
	 * @param myEnrichFns The myEnrichFns to set.
	 */
	public void setMyEnrichFns(List<EnrichmentFunction> myEnrichFns) {
		this.myEnrichFns = myEnrichFns;
		ListIterator it = this.myEnrichFns.listIterator();
		while(it.hasNext()){
			EnrichmentFunction enrFn = (EnrichmentFunction) it.next();
			enrFn.setMyEnrItem(this);
		}
	}


	/**
	 * 
	 */
	public boolean interactsWith(XFEMElement e){
		return this.getMyGeometry().interactsWith(e);
	}
	
	
	/**
	 * Gets the enrichment detector that belongs to this
	 * enrichment item and it sets enriched nodes.
	 */
	public void treatEnrichment(){
		this.getMyEnrDetector().setEnrichedNodes(this);
	}
	
	
	/**
	 * 
	 */
	public abstract void resolveLinearDependency();
	
	
	/**
	 * Updates the position of the crack tip. Computes the crack
	 * advance computing the crack direction (angle) and crack 
	 * increment length. Used for NonLocalPrincipalStressDirection
	 * class and BoundaryElementIncrement class.
	 * @param dirLaw The provided direction law for crack angle 
	 * computation.
	 * @param incLaw The provided increment law for crack increment
	 * computation.
	 */
	public abstract void updateMyGeometry(NonLocalPrincipalStressDirection dirLaw, BoundaryElementIncrement incLaw);
	
	/**
	 * Updates the position of the crack tip. Computes the crack
	 * advance computing the crack direction (angle) and crack 
	 * increment length.
	 * @param dirLaw The provided direction law for crack angle 
	 * computation.
	 * @param incLaw The provided increment law for crack increment
	 * computation.
	 */
	public abstract void updateMyGeometry(CrackGrowthDirectionLaw dirLaw, CrackGrowthIncrementLaw incLaw);
	
	/**
	 * 
	 * @param model The provided XFemModel.
	 */
	public abstract void updateEnrichment(XFemModel model);


	/**
	 * @return Returns the numDofOnWhichEnrichFnsAct.
	 */
	public int[] getNumDofOnWhichEnrichFnsAct() {
		return numDofOnWhichEnrichFnsAct;
	}


	/**
	 * @param numDofOnWhichEnrichFnsAct The numDofOnWhichEnrichFnsAct to set.
	 */
	public void setNumDofOnWhichEnrichFnsAct(int[] numDofOnWhichEnrichFnsAct) {
		this.numDofOnWhichEnrichFnsAct = numDofOnWhichEnrichFnsAct;
	}


	/**
	 * @return Returns the totalNumberOfAdditionalDofs.
	 */
	public int getTotalNumberOfAdditionalDofs() {
		return totalNumberOfAdditionalDofs;
	}


	/**
	 * @param totalNumberOfAdditionalDofs The totalNumberOfAdditionalDofs to set.
	 */
	public void setTotalNumberOfAdditionalDofs(int totalNumberOfAdditionalDofs) {
		this.totalNumberOfAdditionalDofs = totalNumberOfAdditionalDofs;
	}

	/**
	 * 
	 * @return
	 */
	public int getTotalNumberOfEnrDofsPerNode(){
		return 0;
	}
	
}
